package com.yuanqunsoft.alimigration.action;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.ServletActionContext;
import org.json.JSONObject;

import com.opensymphony.xwork2.ActionSupport;
import com.yuanqunsoft.alimigration.bean.RuleBean;
import com.yuanqunsoft.alimigration.bean.RuleImplementBean;
import com.yuanqunsoft.alimigration.common.ParseEngineType;
import com.yuanqunsoft.alimigration.common.PropertiesUtil;
import com.yuanqunsoft.alimigration.service.IRuleImplementService;
import com.yuanqunsoft.alimigration.service.IRuleService;
import com.yuanqunsoft.alimigration.utils.JsonResult;

public class RuleImplementAction extends ActionSupport {

    private static Logger logger = LogManager.getLogger(RuleImplementAction.class);

    private IRuleService ruleService;
    private IRuleImplementService ruleImplementService;
    private boolean success;
    private JsonResult result;
    private int ruleImpId;
    private List<?> datas;
    // 从js得到的class文件
    private File upload;
    // 得到的class文件的名字，由js隐藏的方式得到，就是className
    private String uploadFileName;
    
    private int start;
    private int limit;

    public String Page() {
        return "page";
    }

    public String conRules() throws Exception {
        JSONObject json = new JSONObject(datas.get(0).toString());
        String rulId = json.getString("rulId");
        RuleImplementBean rs = this.ruleImplementService.getRuleImplementById(ruleImpId);
        RuleBean rule = this.ruleService.getRuleById(Integer.parseInt(rulId));
        // this.ruleImplementService.selectRules(rs, rule);
        this.setSuccess(true);
        return "success";
    };

    public String delRuleImplement() throws Exception {
        try {
            RuleImplementBean ruleImplement = this.getRuleImplementService().getRuleImplementById(ruleImpId);
            this.getRuleImplementService().delete(ruleImplement);
            this.setSuccess(true);
        } catch (Exception e) {
            e.printStackTrace();
            this.setSuccess(false);
        }
        return "success";
    };

    // 保存文件到本地
    private String saveFile(String path) throws Exception {

        File dir = new File(path);
        if (!dir.exists()) {
            dir.mkdirs();
        }

        // 如果是zip文件，将class文件和配置文件解压到相应目录
        if (uploadFileName.endsWith(".zip")) {
            logger.debug("upload zip file : " + uploadFileName);

            try {
                ZipFile zip = new ZipFile(upload);
                Enumeration<?> e = zip.entries();
                while (e.hasMoreElements()) {
                    ZipEntry entry = (ZipEntry) e.nextElement();
                    if (!entry.isDirectory()) {
                        String name = entry.getName();
                        if (name.endsWith(".class")) {
                            save(zip, entry, path);
                        } else if (name.endsWith(".txt") || name.endsWith(".properties") || name.endsWith(".xml")) {
                            save(zip, entry, PropertiesUtil.getRuleImplPropertiesDir().getAbsolutePath());
                        }
                    }
                }
                zip.close();
            } catch (IOException e) {
                logger.debug(e);
                e.printStackTrace();
            }
        } else {
            // 否则是单个class文件
            logger.debug("upload single class file : " + upload.getName() + "to [ " + path + " ]");

            InputStream is = new FileInputStream(upload);
            OutputStream os = new FileOutputStream(new File(dir, uploadFileName));
            byte[] buf = new byte[1024];
            int len = -1;
            while ((len = is.read(buf)) != -1) {
                os.write(buf, 0, len);
            }
            is.close();
            os.close();
        }
        return path.replace("\\\\", "\\") + "\\" + uploadFileName;
    }

    private void save(ZipFile zip, ZipEntry entry, String path) throws IOException {
        logger.debug("upload file [" + entry.getName() + " ] to [ " + path + " ]");
        int buffer = 2048;
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        bis = new BufferedInputStream(zip.getInputStream(entry));
        int count;
        byte[] data = new byte[buffer];
        FileOutputStream fos = new FileOutputStream(path + File.separator + entry.getName());
        bos = new BufferedOutputStream(fos, buffer);
        while ((count = bis.read(data, 0, buffer)) != -1) {
            bos.write(data, 0, count);
        }
        bos.flush();
        bos.close();
        bis.close();
    }

    // 添加一个ruleImplement
    public String addRuleImplement() throws Exception {

        JSONObject json = new JSONObject(datas.get(0).toString());// 转换为json对象格式
        // 将json对象转换为javaBean

        // 得到上传的ruleImplement的parseEngineType、rulId、className
        ParseEngineType parseEngineType = ParseEngineType.valueOf(json.getInt("parseEngineType"));
        int rulId = json.getInt("rulId");

        // 将得到信息放入ruleImplement
        RuleImplementBean ruleImplementBean = new RuleImplementBean();
        RuleBean rule = this.ruleService.getRuleById(rulId);
        ruleImplementBean.setRulId(rule.getRulId());
        ruleImplementBean.setRulName(rule.getRulName());
        ruleImplementBean.setParseEngineType(parseEngineType.ordinal());

        // 存储class文件的根目录
        String path = PropertiesUtil.getRuleImplClassDir(parseEngineType).getAbsolutePath();

        // 从根目录下保存文件
        this.saveFile(path);

        // 判读是否有重复的ruleImplement，如果有不再向数据库中添加，直接覆盖
        uploadFileName = uploadFileName.split("\\.")[0];
        if (!this.ruleImplementService.isInfoExisted(rule, uploadFileName, parseEngineType.ordinal())) {

            // 保存ruleImplement到数据库
            ruleImplementBean.setClassName(uploadFileName);
            this.ruleImplementService.save(ruleImplementBean);
        }

        this.setSuccess(true);
        return "success";
    };

    public String getRules() throws Exception {
        List<RuleBean> list = this.ruleImplementService.getAllRules();
        setResult(new JsonResult(list, list.size()));
        this.setSuccess(true);
        return "success";
    };

    public String ruleImplementList() throws Exception {
        List<RuleImplementBean> list = this.ruleImplementService.getAllRuleImplement(start, limit);
        setResult(new JsonResult(list, this.ruleImplementService.getAllPage()));
        this.setSuccess(true);
        return "success";
    };

    public IRuleImplementService getRuleImplementService() {
        return ruleImplementService;
    }

    public void setRuleImplementService(IRuleImplementService ruleImplementService) {
        this.ruleImplementService = ruleImplementService;
    }

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public JsonResult getResult() {
        return result;
    }

    public void setResult(JsonResult result) {
        this.result = result;
    }

    public List<?> getDatas() {
        return datas;
    }

    public void setDatas(List<?> datas) {
        this.datas = datas;
    }

    public int getRuleImpId() {
        return ruleImpId;
    }

    public void setRuleImpId(int ruleImpId) {
        this.ruleImpId = ruleImpId;
    }

    public IRuleService getRuleService() {
        return ruleService;
    }

    public void setRuleService(IRuleService ruleService) {
        this.ruleService = ruleService;
    }

    public File getUpload() {
        return upload;
    }

    public void setUpload(File upload) {
        this.upload = upload;
    }

    public String getUploadFileName() {
        return uploadFileName;
    }

    public void setUploadFileName(String uploadFileName) {
        this.uploadFileName = uploadFileName;
    }

    public int getStart() {
        return start;
    }

    public void setStart(int start) {
        this.start = start;
    }

    public int getLimit() {
        return limit;
    }

    public void setLimit(int limit) {
        this.limit = limit;
    }

}
